import axios, { AxiosHeaders } from 'axios'
import type {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError,
  InternalAxiosRequestConfig,
} from 'axios'
import type { ApiResponse, ApiError, AnyJson } from '@/types'
import { createLogger } from '@/utils/logger'

const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || (import.meta.env.DEV ? '' : 'http://localhost:8083')

function generateRequestId(): string {
  return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`
}

// 创建API专用logger
const apiLogger = createLogger('API')

class ApiClient {
  private client: AxiosInstance

  constructor() {
    this.client = axios.create({
      baseURL: API_BASE_URL, // API基础URL
      timeout: 10000,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    this.setupInterceptors()
  }

  private setupInterceptors() {
    type RequestMetadata = { startTime: number; requestId: string }
    type ExtendedInternalConfig = InternalAxiosRequestConfig & { metadata?: RequestMetadata }
    // Request interceptor
    this.client.interceptors.request.use(
      (config: ExtendedInternalConfig) => {
        const requestId = generateRequestId()
        config.metadata = { startTime: Date.now(), requestId }
        const token = localStorage.getItem('token')
        if (!config.headers) {
          config.headers = new AxiosHeaders()
        }
        if (token) {
          ;(config.headers as AxiosHeaders).set('Authorization', `Bearer ${token}`)
        }
        // 透传追踪ID，便于与后端日志对齐
        ;(config.headers as AxiosHeaders).set('X-Request-Id', requestId)
        if (import.meta.env.DEV) {
          const { method, url, params, data } = config
          apiLogger.apiRequest(method || 'GET', url || '', { params, data, requestId })
        }
        return config
      },
      (error) => {
        return Promise.reject(error)
      },
    )

    // Response interceptor - 根据文档，所有接口返回统一的 ResponseResult<T> 格式
    this.client.interceptors.response.use(
      (response: AxiosResponse<ApiResponse<unknown>>) => {
        const metadata = (response.config as ExtendedInternalConfig).metadata
        if (import.meta.env.DEV) {
          const duration = Date.now() - (metadata?.startTime ?? Date.now())
          apiLogger.apiResponse(
            response.config.method || 'GET',
            response.config.url || '',
            response.status,
            duration,
            { code: (response.data as { code?: number })?.code, requestId: metadata?.requestId },
          )
        }
        const { data } = response
        
        // 优先按统一 ResponseResult 处理
        const dr = data as Partial<{ code: number; msg: string; data: unknown }>
        if (typeof dr.code === 'number') {
          if (dr.code === 200) {
            return response
          }
          return Promise.reject({
            code: dr.code,
            message: dr.msg || '请求失败',
            details: dr.data,
          })
        }

        // 兼容部分接口返回 { success: boolean, data, message }
        const sr = data as { success?: boolean; data?: unknown; message?: string }
        if (typeof sr.success === 'boolean') {
          if (sr.success) {
            return response
          }
          return Promise.reject({
            code: 0,
            message: sr.message || '请求失败',
            details: sr.data,
          })
        }

        // 兼容直接返回数据的情况（如某些查询接口）
        if (data && (Array.isArray(data) || typeof data === 'object')) {
          return response
        }

        // 兜底：未知返回结构，直接透传
        return response
      },
      (error: AxiosError<ApiResponse<unknown>>) => {
        const cfg = error.config as ExtendedInternalConfig | undefined
        const metadata = cfg?.metadata
        if (import.meta.env.DEV) {
          const duration = metadata?.startTime ? Date.now() - metadata.startTime : undefined
          apiLogger.apiError(
            cfg?.method || 'GET',
            cfg?.url || '',
            {
              status: error.response?.status || 'NETWORK',
              data: error.response?.data,
              requestId: metadata?.requestId,
            },
            duration,
          )
        }
        let apiError: ApiError

        if (error.response) {
          // Server responded with error
          const { data, status } = error.response
          apiError = {
            code: data?.code || status,
            message: data?.msg || this.getErrorMessage(status),
            details: data?.data as AnyJson | undefined,
          }
        } else if (error.request) {
          // Request made but no response
          apiError = {
            code: 0,
            message: '网络连接失败，请检查网络后重试',
          }
        } else {
          // Something else happened
          apiError = {
            code: 0,
            message: error.message || '请求发生错误',
          }
        }

        // Handle specific error cases
        if (apiError.code === 401) {
          // 【重要】401认证错误处理优化
          // 不立即清除token和用户信息，让页面组件自己处理
          // 避免在关键流程（如结算）中突然丢失用户状态
          // ⚠️ 请勿删除此逻辑，否则会影响用户体验
          const isCheckoutPage = window.location.pathname.includes('/checkout')
          const isAuthPage = window.location.pathname.includes('/auth/')
          
          if (!isCheckoutPage && !isAuthPage) {
            // 非结算页面和非认证页面才清除状态并跳转
            localStorage.removeItem('token')
            localStorage.removeItem('user')
            window.location.href = '/login'
          }
          // 结算页面的401错误由组件自己处理，提供更好的用户体验
        }

        return Promise.reject(apiError)
      },
    )
  }

  private getErrorMessage(status: number): string {
    switch (status) {
      case 400:
        return '请求参数错误'
      case 401:
        return '未授权，请重新登录'
      case 403:
        return '无权限访问'
      case 404:
        return '请求的资源不存在'
      case 500:
        return '服务器内部错误'
      case 503:
        return '服务暂时不可用'
      default:
        return '请求失败'
    }
  }

  public get<T>(url: string, config?: AxiosRequestConfig): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.client.get(url, config)
  }

  public post<T, B extends object = object>(
    url: string,
    data?: B,
    config?: AxiosRequestConfig,
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.client.post(url, data, config)
  }

  public put<T, B extends object = object>(
    url: string,
    data?: B,
    config?: AxiosRequestConfig,
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.client.put(url, data, config)
  }

  public delete<T>(
    url: string,
    config?: AxiosRequestConfig,
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    return this.client.delete(url, config)
  }

  public upload<T>(
    url: string,
    file: File,
    onProgress?: (progress: number) => void,
  ): Promise<AxiosResponse<ApiResponse<T>>> {
    const formData = new FormData()
    formData.append('file', file)

    return this.client.post(url, formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
      onUploadProgress: (progressEvent) => {
        if (progressEvent.total && onProgress) {
          const progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
          onProgress(progress)
        }
      },
    })
  }
}

export const apiClient = new ApiClient()
export default apiClient
